home *** CD-ROM | disk | FTP | other *** search
- Page 55,132
- Title SEND - Send a file using XMODEM protocol
-
- SPECIAL Equ 0 ;If true, include data size in block
-
- If SPECIAL
- BLOCK Struc
- B_SOH Db 001H ;Start of header
- B_BLK1 Db 000H ;Block number
- B_BLK2 Db 0FFH ;(Block number)'
- B_CNT Db ? ;Count of bytes used in the data area
- B_DATA Db 128 Dup (?) ;The data area
- B_CHKSUM Db ? ;Checksum of the data
- BLOCK Ends
- Else
- BLOCK Struc
- B_SOH Db 001H ;Start of header
- B_BLK1 Db 000H ;Block number
- B_BLK2 Db 0FFH ;(Block number)'
- B_DATA Db 128 Dup (?) ;The data area
- B_CHKSUM Db ? ;Checksum of the data
- BLOCK Ends
- Endif
-
- ERROR Macro N
- Mov AH,09H ;Display the error message
- Lea DX,ERRMSG&N ;
- Int 021H ;
- Mov AX,04C10H+N ;And leave
- Int 021H ;
- Endm
-
- CODE Segment Public 'CODE'
- CODE Ends
-
- DATA Segment Public 'DATA'
-
- BAUD_TABLE Label Word
- Dw 9600 ;
- Dw 4800 ;
- Dw 2400 ;
- Dw 1200 ;
- Dw 600 ;
- Dw 300 ;
- Dw 150 ;
- Dw 110 ;
-
- FILENAME Db 64 Dup (0) ;Name of file to send
-
- BUFFER BLOCK <> ;The block buffer
-
- ERRMSG0 Db '?No input file specified',13,10,'$'
- ERRMSG1 Db '?Unable to open input file',13,10,'$'
- ERRMSG2 Db '?Invalid baud rate specified',13,10,'$'
- ERRMSG3 Db '?Receiver time-out occurred',13,10,'$'
- ERRMSG4 Db '?Error while reading the input file',13,10,'$'
- ERRMSG5 Db '^C',13,10,'%Transmission aborted via control-C',13,10,'$'
-
- TXTMSG1 Db 'Waiting for receiver...',13,10,'$'
- TXTMSG2 Db 'Block number '
- TXTNUM2 Db '0 ',13,'$'
- TXTMSG3 Db 10,'Transmission complete',13,10,'$'
- TXTMSG4 Db 'No retries needed',13,10,'$'
- TXTMSG5 Db 'Retry count was '
- TXTNUM5 Db '0 ',13,10,'$'
-
- MODE Db 11101011B ;9600 baud, odd parity, 1 stop bit,
- ;8 bit character
-
- BLOCK_COUNT Dw 0 ;Total block count
- RETRY_COUNT Dw 0 ;Retry count
-
- DATA Ends
-
- STACK Segment Stack 'STACK'
-
- Dw 128 Dup (?) ;Program stack
-
- STACK Ends
-
- CODE Segment Public 'CODE'
-
- Assume CS:CODE,DS:Nothing,ES:Nothing,SS:STACK
-
- MAIN Proc Near
- Sti ;Enable interrupts
- Mov AX,DATA ;Set up ES
- Mov ES,AX ;
-
- Assume ES:DATA
-
- Cld ;Make sure the direction flag is clear
- Mov SI,080H ;Use SI to get the file name
- Lodsb ;Get the length
- Or AL,AL ;Is there anything??
- Jnz MAIN01 ;Yes. Proceed
- MAIN00: Mov AX,ES ;Set up DS
- Mov DS,AX ;
-
- Assume DS:DATA
-
- ERROR 0 ;Nope. Die!
-
- Assume DS:Nothing
-
- MAIN01: Cbw ;Make it a word count
- Mov CX,AX ;Copy to CX
-
- MAIN05: Jcxz MAIN00 ;If nothing left, error!
- Dec CX ;Decrement the character count
- Lodsb ;And get the character
- Cmp AL,020H ;Space or less??
- Ja MAIN10 ;Nope. Start the file name
- Jmp Short MAIN05 ;Try again...
-
- MAIN10: Lea DI,FILENAME ;Point DI to the file name buffer
- MAIN11: Stosb ;Store the character
- Jcxz MAIN20 ;Got the file name. Open the file
- Dec CX ;Decrement the character count
- Lodsb ;Get the next character
- Cmp AL,020H ;Is it a displayable character
- Ja MAIN11 ;Yes. Put it in the file name
-
- MAIN13: Jcxz MAIN20 ;No more characters?
- Dec CX ;Decrement the count
- Lodsb ;Get another character
- Cmp AL,020H ;Space or less??
- Ja MAIN15 ;Yes. See if it's a number
- Jmp Short MAIN13 ;Keep looking
-
- MAIN15: Xor DX,DX ;Clear DX
- MAIN16: Cmp AL,'0' ;Is this a digit??
- Jae MAIN18 ;Yes.
- MAIN17: ERROR 2 ;Not a valid baud rate
-
- MAIN18: Cmp AL,'9' ;Still a digit??
- Ja MAIN17 ;Nope.
- Sub AL,'0' ;Convert to binary
- Cbw ;Convert to a word
- Shl DX,1 ;Double the previous number
- Mov BX,DX ;Save in BX for a bit
- Shl DX,1 ;
- Shl DX,1 ;
- Add DX,BX ;Now DX = (Old DX)*10
- Add DX,AX ;Add in the last digit
- Jcxz MAIN19 ;All done.
- Dec CX ;Decrement the character count
- Lodsb ;And get a character
- Cmp AL,020H ;Space or less?
- Ja MAIN16 ;
-
- MAIN19: Mov AX,DX ;Put the baud rate in AX
- Lea DI,BAUD_TABLE ;Point to the baud rate table
- Mov CX,8 ;Eight entries in the table
- Repne Scasw ;Look for this baud rate
- Jne MAIN17 ;No good! Die!
- Mov AL,CL ;Get the index
- Mov CL,5 ;And position it
- Shl AL,CL ;
- Or AL,00001011B ;Odd parity, 1 stop bit, 8 bit character
- Mov MODE,AL ;And save it
-
- MAIN20: Mov AX,ES ;Set up DS
- Mov DS,AX ;
-
- Assume DS:DATA
-
- Mov AX,03D00H ;Open the file for read-only
- Lea DX,FILENAME ;
- Int 021H ;
- Jnc MAIN25 ;Proceed!
- ERROR 1 ;File not found!
-
- MAIN25: Mov BX,AX ;Put the handle in BX
-
- Xor AH,AH ;Initialize the RS232 channel
- Mov AL,MODE ;
- Xor DX,DX ;On channel zero
- Int 014H ;
-
- Mov AH,09H ;Display the "Waiting..." message
- Lea DX,TXTMSG1 ;
- Int 021H ;
-
- Mov CX,64 ;This shall be our original timeout
- MAIN30: Mov AH,06H ;See if a character is waiting
- Mov DL,0FFH ;
- Int 021H ;
- Jz MAIN32 ;Nope.
- Cmp AL,3 ;Is it a control-C??
- Jne MAIN32 ;
-
- Mov AH,03EH ;Close the input file
- Int 021H ;
- ERROR 5 ;And die
-
- MAIN32: Mov AH,02H ;Get a character from the serial port
- Xor DX,DX ;(channel 0)
- Int 014H ;
- Test AH,08EH ;Any error occurred??
- Jnz MAIN31 ;Yes. Ignore it.
- Cmp AL,015H ;Is this a NAK??
- Je MAIN35 ;Yes. Start the transmission.
- MAIN31: Loop MAIN30 ;Repeat until CX = 0
- Mov AH,03EH ;Close the input file
- Int 021H ;
- ERROR 3 ;And die!
-
- MAIN35: Mov AH,03FH ;Read the file
- Mov CX,128 ;Up to 128 bytes
- Lea DX,BUFFER.B_DATA ;Into our buffer
- Int 021H ;
- Jnc MAIN40 ;Got it; now ship it
- Mov AH,03EH ;Close the input file
- Int 021H ;
- ERROR 4 ;And die (for some unknown reason)
-
- MAIN40: Or AX,AX ;Did we reach the end of the file??
- Jz MAIN80 ;Yes. Tell the receiver
-
- Inc BUFFER.B_BLK1 ;Adjust the block numbers
- Dec BUFFER.B_BLK2 ;
- If SPECIAL
- Mov BUFFER.B_CNT,AL ;Store the count of bytes used
- Endif
- Inc BLOCK_COUNT ;Increment the block count
-
- Lea SI,BUFFER.B_DATA ;Compute the checksum
- Xor AH,AH ;Clear AH
- Xor DX,DX ;Keep the checksum in DX
- Mov CX,128 ;Repeat for 128 bytes
- MAIN45: Lodsb ;Get a byte
- Add DX,AX ;Add it to DX
- Loop MAIN45 ;And repeat
- Mov AX,DX ;Put the sum in AX
- Mov DL,255 ;Now divide by 255
- Div DL ;
- Mov BUFFER.B_CHKSUM,AH ;Store the remainder as the checksum
-
- Lea DI,TXTNUM2 ;Fill in the block number
- Mov AX,BLOCK_COUNT ;
- Call FILL_NUM ;
- Mov AH,09H ;Display the block number
- Lea DX,TXTMSG2 ;
- Int 021H ;
-
- ;
- ; Send the block we have
- ;
-
- MAIN50: Lea SI,BUFFER ;Point to the block
- Mov CX,(Size BLOCK) ;Get the size of the block
- MAIN51: Lodsb ;Get the byte to send
- Mov AH,01H ;Send the byte
- Xor DX,DX ;On channel zero
- Int 014H ;
- Loop MAIN51 ;
-
- Call GET_RESPONSE ;Get the response
- Cmp AL,015H ;Negative acknowledgement??
- Je MAIN50 ;Yes. Try again
- Jmp MAIN35 ;Go get the next piece (of ass?)
-
- ;
- ; End of file...
- ;
-
- MAIN80: Mov AH,09H ;Display the EOT message
- Lea DX,TXTMSG3 ;
- Int 021H ;
-
- MAIN82: Mov AX,0104H ;Send the EOT
- Xor DX,DX ;
- Int 014H ;
-
- Call GET_RESPONSE ;Get the response
- Cmp AL,015H ;Negatory??
- Je MAIN82 ;Yes. Try again!
-
- MAIN90: Mov AH,03EH ;Close the input file
- Int 021H ;
-
- Cmp RETRY_COUNT,0 ;Did we have to do any retries??
- Jne MAIN95 ;Yes. Fill in the number and display it
-
- Mov AH,09H ;No retries needed
- Lea DX,TXTMSG4 ;
- Int 021H ;
- Jmp Short MAIN99 ;Leave
-
- MAIN95: Lea DI,TXTNUM5 ;Point to the buffer
- Mov AX,RETRY_COUNT ;Get the count
- Call FILL_NUM ;
- Mov AH,09H ;And display the message
- Lea DX,TXTMSG5 ;
- Int 021H ;
-
- MAIN99: Mov AX,04C00H ;And leave
- Int 021H ;
- MAIN Endp
-
- ;
- ; Get a positive or negative response from the receiver.
- ;
-
- GET_RESPONSE Proc Near
- Mov AH,06H ;See if a character is waiting
- Mov DL,0FFH ;
- Int 021H ;
- Jz GETR20 ;Nope.
- Cmp AL,3 ;Is it a control-C??
- Jne GETR20 ;
-
- Mov AH,03EH ;Close the input file
- Int 021H ;
- ERROR 5 ;And leave
-
- GETR20: Mov AH,02H ;Get a character from the serial port
- Xor DX,DX ;(channel zero)
- Int 014H ;
- Test AH,08EH ;Did an error occur??
- Jnz GET_RESPONSE ;Yes. Ignore the character
- Cmp AL,005H ;Is this an ACK??
- Je GETR30 ;Yes. Leave
- Cmp AL,015H ;How 'bout a NAK??
- Jne GET_RESPONSE ;Nope. Check again!
- Inc RETRY_COUNT ;Bump the retry count
- GETR30: Ret ;And return
- GET_RESPONSE Endp
-
- ;
- ;
- ;
-
- FILL_NUM Proc Near
- Xor CX,CX ;Clear the character count
- Mov SI,10 ;Use SI to divide with
- FILL10: Xor DX,DX ;
- Div SI ;Divide DX:AX by SI (10)
- Add DL,'0' ;Convert DL to ASCII
- Push DX ;Save it on the stack
- Inc CX ;Increment the character count
- Or AX,AX ;Any more to do??
- Jnz FILL10 ;Yes. Keep going
- Cld ;(just to be sure)
- FILL20: Pop AX ;Get a character from the stack
- Stosb ;And store it
- Loop FILL20 ;Repeat CX times
- Ret ;And return
- FILL_NUM Endp
-
- CODE Ends
- End MAIN